﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using OpenSSL.X509;
using Sicurezza.Client.Manager;
using OpenSSL.Core;
using OpenSSL.Crypto;
using Sicurezza.Entita;

namespace Sicurezza.Client.Controlli
{
    public partial class CertificateControl : UserControl
    {
        private X509Certificate Certificato { get; set; }
        private RSA key { get; set; }
        private string CurrentReqId;

        public event EventHandler OpeningRenew;

        public CertificateControl()
        {
            InitializeComponent();
            ValidityManager.VerifyReceived += new EventHandler(ValidityManager_VerifyReceived);
        }

        void ValidityManager_VerifyReceived(object sender, EventArgs e)
        {
            OCSPResult result = (OCSPResult)sender;
            switch (result)
            {
                case OCSPResult.Valid:
                    MsgBox.Info("Certificate is valid");
                    break;

                case OCSPResult.Revoked:
                    //DateTime revocationDate = Convert.ToDateTime(sender);
                    //if (revocationDate != null)
                    //    MsgBox.Error("Certificate revoked since " + revocationDate.ToString());
                    //else
                        MsgBox.Error("Certificate revoked by CA");
                    break;

                case OCSPResult.Unknow:
                    MsgBox.Error("Certificate unknown");
                    break;

                default:
                    break;
            }
        }


        private void ShowCertificate(X509Certificate cert)
        {
            Certificato = cert;
            certificateViewControl.EditMode = false;

            certificateViewControl.PublicKeyAlgorithm = "rsaEncryption";
            certificateViewControl.PublicKey = Certificato.PublicKey.GetRSA().PublicModulus.ToHexString();
            certificateViewControl.SubjectC = Certificato.Subject.Country;
            certificateViewControl.SubjectO = Certificato.Subject.Organization;
            certificateViewControl.SubjectOU = Certificato.Subject.OrganizationUnit;
            certificateViewControl.SubjectCN = Certificato.Subject.Common;

            certificateViewControl.Version = "3";
            certificateViewControl.Serial = Certificato.SerialNumber.ToString();
            certificateViewControl.NotBefore = Certificato.NotBefore.ToString();
            certificateViewControl.NotAfter = Certificato.NotAfter.ToString();
            certificateViewControl.AlgorithmID = "rsaEncryption";
            certificateViewControl.IssuerC = Certificato.Issuer.Country;
            certificateViewControl.IssuerO = Certificato.Issuer.Organization;
            certificateViewControl.IssuerOU = Certificato.Issuer.OrganizationUnit;
            certificateViewControl.IssuerCN = Certificato.Issuer.Common;

            certificateViewControl.DigitalSignature = X509Manager.IsSignAllowed(Certificato);
            certificateViewControl.KeyEncipherment = X509Manager.IsEncipherAllowed(Certificato);

            certificateViewControl.SubjectEmail = X509Manager.GetEmail(Certificato);

        }

        void ValidityManager_VerifyErr(object sender, EventArgs e)
        {
            
        }

        void ValidityManager_VerifyOk(object sender, EventArgs e)
        {
            
        }

        public void Reset()
        {
            validityButton.Enabled = true;
            RenewButton.Enabled = true;
            RevokeButton.Enabled = true;
            validityButton.Visible = true;
            RenewButton.Visible = true;
            RevokeButton.Visible = true;
            certificateViewControl.Reset();
        }

        public void OpenString(string cert)
        {
            ShowCertificate(new X509Certificate(new BIO(cert)));
        }

        public void SaveCertificate()
        {
            string path = "";
            FileDialog fb = new SaveFileDialog();
            fb.FileName = "cert.pem";
            if (fb.ShowDialog() == DialogResult.OK)
                path = fb.FileName;


            if (!string.IsNullOrEmpty(path))
            {
                FileManager.SaveCertificate(Certificato, path);
                MessageBox.Show("Certificato salvato con successo",
                    "Salvataggio effettuato",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Information);
            }
        }


        public void OpenFile(string filename)
        {
            X509Certificate c = null;
            try
            {
                c = new X509Certificate(new BIO(FileManager.LoadCertificateFromFile(filename)));
            }
            catch (OpenSslException ex)
            {
                MsgBox.Error("File is not in valid PEM format.");
                return;
            }

            ShowCertificate(c);

            validityButton.Visible = true;
            RevokeButton.Visible = false;
            RenewButton.Visible = false;
        }

        public void Open(string serial)
        {
            X509Certificate c = X509Manager.Get(serial);
            ShowCertificate(c);
        }

        private void validityButton_Click(object sender, EventArgs e)
        {
            ValidityManager.Validate(Certificato.SerialNumber);
        }

        private void RenewButton_Click(object sender, EventArgs e)
        {
            PasswordForm pf = new PasswordForm();
            if (pf.ShowDialog() != DialogResult.OK)
                return;

            CryptoKey privatekey = null;
            try
            {
                privatekey = KeyManager.Load(Certificato.SerialNumber, pf.Password);

            }
            catch (ManagerException me)
            {
                MsgBox.Error(me.Message);
                return;
            }
            ChooseKeyLenght ckl = new ChooseKeyLenght();
            if (ckl.ShowDialog() != DialogResult.OK || ckl.KeyLenght == 0)
                return;

            RSA newkey = KeyManager.Generate(ckl.KeyLenght);

            string RenId = RenewManager.SendRequest(Certificato, privatekey, newkey);


            //-- Se la richiesta è stata accettata, sposto il certificato in attesa
            //-- assieme alla nuova chiave privata
            //
            MsgBox.RequestOk();
            pf = new PasswordForm();
            do
            {
                pf.ShowDialog();
            } while (pf.DialogResult != DialogResult.OK);

            RenewManager.Save(RenId, Certificato.SerialNumber, newkey, pf.Password);


            OpeningRenew(RenId, null);
        }

        private void RevokeButton_Click(object sender, EventArgs e)
        {
            PasswordForm pf = new PasswordForm();
            if (pf.ShowDialog() != DialogResult.OK)
                return;

            bool revoked = false;
            try
            {
                revoked = RevokeManager.SendRequest(Certificato, pf.Password);
            }
            catch (ManagerException ex)
            {
                MsgBox.Error(ex.Message);
                return;
            }

            if (revoked)
            {
                FileManager.MoveToRevoked(Certificato.SerialNumber);
                MsgBox.RevokedOk();
                Reset();
                Visible = false;
            }
        }
    }
}
